import {
  Injectable,
  NestInterceptor,
  ExecutionContext,
  CallHandler,
  HttpException,
  HttpStatus,
} from '@nestjs/common';
import { Observable, throwError } from 'rxjs';
import { tap, catchError } from 'rxjs/operators';
import { Request, Response } from 'express';
import { LoggerService } from '../logger/logger.service';

@Injectable()
export class LoggerInterceptor implements NestInterceptor {
  constructor(private readonly logger: LoggerService) {
    this.logger.setContext('LoggerInterceptor');
  }

  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const request = context.switchToHttp().getRequest<Request>();
    const { method, url, ip, body, query, params } = request;
    const userAgent = request.get('user-agent') || '';
    const contentLength = request.get('content-length');

    // 请求开始时间
    const now = Date.now();

    // 记录请求信息
    this.logger.log({
      message: `收到请求 ${method} ${url}`,
      method,
      url,
      ip,
      userAgent,
      contentLength,
      body: method !== 'GET' ? body : undefined,
      query: Object.keys(query).length ? query : undefined,
      params: Object.keys(params).length ? params : undefined,
    });

    return next.handle().pipe(
      tap((data) => {
        const response = context.switchToHttp().getResponse<Response>();
        const { statusCode } = response;
        const responseTime = Date.now() - now;

        // 记录响应信息
        this.logger.log({
          message: `请求完成 ${method} ${url} ${statusCode}`,
          responseTime: `${responseTime}ms`,
          statusCode,
        });
      }),
      catchError((error) => {
        const responseTime = Date.now() - now;
        
        // 获取错误状态码和消息
        const status =
          error instanceof HttpException
            ? error.getStatus()
            : HttpStatus.INTERNAL_SERVER_ERROR;
        const message =
          error instanceof HttpException
            ? error.message
            : `内部服务器错误: ${error.message}`;

        // 记录错误信息
        this.logger.error(
          {
            message: `请求失败 ${method} ${url} ${status}`,
            error: message,
            responseTime: `${responseTime}ms`,
          },
          error.stack,
        );

        return throwError(() => error);
      }),
    );
  }
}
